import requests
import json
import os
from typing import Dict, List, Optional
from datetime import datetime
import logging

class LLMService:
    """大模型服务核心类 - 支持DeepSeek等主流LLM"""
    
    def __init__(self, api_key: str = None, base_url: str = None, provider: str = 'deepseek'):
        self.provider = provider.lower()
        self.api_key = api_key or os.getenv('LLM_API_KEY', 'your-api-key-here')
        
        # DeepSeek配置
        if self.provider == 'deepseek':
            self.base_url = base_url or os.getenv('DEEPSEEK_BASE_URL', 'https://api.deepseek.com/v1')
            self.model = os.getenv('DEEPSEEK_MODEL', 'deepseek-chat')
            self.max_tokens = int(os.getenv('DEEPSEEK_MAX_TOKENS', '4000'))
            self.temperature = float(os.getenv('DEEPSEEK_TEMPERATURE', '0.7'))
        # OpenAI配置
        elif self.provider == 'openai':
            self.base_url = base_url or os.getenv('OPENAI_BASE_URL', 'https://api.openai.com/v1')
            self.model = os.getenv('OPENAI_MODEL', 'gpt-3.5-turbo')
            self.max_tokens = int(os.getenv('OPENAI_MAX_TOKENS', '2000'))
            self.temperature = float(os.getenv('OPENAI_TEMPERATURE', '0.7'))
        # 其他LLM配置
        else:
            self.base_url = base_url or os.getenv('LLM_BASE_URL', 'https://api.deepseek.com/v1')
            self.model = os.getenv('LLM_MODEL', 'deepseek-chat')
            self.max_tokens = int(os.getenv('LLM_MAX_TOKENS', '4000'))
            self.temperature = float(os.getenv('LLM_TEMPERATURE', '0.7'))
        
        # 设置日志
        logging.basicConfig(level=logging.INFO)
        self.logger = logging.getLogger(__name__)
    
    def call_llm(self, messages: List[Dict], **kwargs) -> Dict:
        """调用大模型API"""
        try:
            headers = {
                'Authorization': f'Bearer {self.api_key}',
                'Content-Type': 'application/json'
            }
            
            # 根据不同的LLM提供商调整请求格式
            if self.provider == 'deepseek':
                data = {
                    'model': kwargs.get('model', self.model),
                    'messages': messages,
                    'max_tokens': kwargs.get('max_tokens', self.max_tokens),
                    'temperature': kwargs.get('temperature', self.temperature),
                    'stream': False
                }
            elif self.provider == 'openai':
                data = {
                    'model': kwargs.get('model', self.model),
                    'messages': messages,
                    'max_tokens': kwargs.get('max_tokens', self.max_tokens),
                    'temperature': kwargs.get('temperature', self.temperature)
                }
            else:
                # 通用格式
                data = {
                    'model': kwargs.get('model', self.model),
                    'messages': messages,
                    'max_tokens': kwargs.get('max_tokens', self.max_tokens),
                    'temperature': kwargs.get('temperature', self.temperature)
                }
            
            response = requests.post(
                f"{self.base_url}/chat/completions",
                headers=headers,
                json=data,
                timeout=180  # 增加到180秒，AI助手需要更长时间
            )
            
            if response.status_code == 200:
                result = response.json()
                return {
                    'success': True,
                    'content': result['choices'][0]['message']['content'],
                    'usage': result.get('usage', {}),
                    'model': result.get('model', ''),
                    'provider': self.provider
                }
            else:
                self.logger.error(f"{self.provider.upper()} API调用失败: {response.status_code} - {response.text}")
                return {
                    'success': False,
                    'error': f"{self.provider.upper()} API调用失败: {response.status_code}",
                    'content': None
                }
                
        except requests.exceptions.Timeout:
            self.logger.error(f"{self.provider.upper()} API请求超时")
            return {
                'success': False,
                'error': f"{self.provider.upper()} API请求超时，请稍后重试",
                'content': None
            }
        except requests.exceptions.ConnectionError:
            self.logger.error(f"{self.provider.upper()} API连接失败")
            return {
                'success': False,
                'error': f"{self.provider.upper()} API连接失败，请检查网络连接",
                'content': None
            }
        except Exception as e:
            self.logger.error(f"{self.provider.upper()}服务异常: {str(e)}")
            return {
                'success': False,
                'error': f"{self.provider.upper()}服务异常: {str(e)}",
                'content': None
            }
    
    def generate_text(self, prompt: str, **kwargs) -> str:
        """生成文本的简化接口"""
        messages = [{'role': 'user', 'content': prompt}]
        result = self.call_llm(messages, **kwargs)
        
        if result['success']:
            return result['content']
        else:
            raise Exception(f"文本生成失败: {result['error']}")
    
    def generate_structured_data(self, prompt: str, expected_format: str, **kwargs) -> Dict:
        """生成结构化数据"""
        # 为DeepSeek优化提示词
        if self.provider == 'deepseek':
            full_prompt = f"""
{prompt}

请严格按照以下JSON格式返回结果，不要包含任何其他文字：
{expected_format}

注意：
1. 只返回JSON格式的数据
2. 不要包含markdown代码块标记
3. 确保JSON格式正确，可以被直接解析
"""
        else:
            full_prompt = f"""
{prompt}

请严格按照以下JSON格式返回结果：
{expected_format}

只返回JSON格式的数据，不要包含其他说明文字。
"""
        
        messages = [{'role': 'user', 'content': full_prompt}]
        result = self.call_llm(messages, **kwargs)
        
        if result['success']:
            try:
                # 尝试解析JSON
                content = result['content'].strip()
                
                # 移除可能的markdown代码块标记
                if content.startswith('```json'):
                    content = content[7:-3]  # 移除```json和```
                elif content.startswith('```'):
                    content = content[3:-3]  # 移除```
                
                # 清理可能的额外字符
                content = content.strip()
                
                return json.loads(content)
            except json.JSONDecodeError as e:
                self.logger.error(f"JSON解析失败: {e}")
                self.logger.error(f"原始内容: {result['content']}")
                raise Exception(f"返回格式错误: {e}")
        else:
            raise Exception(f"结构化数据生成失败: {result['error']}")
    
    def validate_response(self, response: str, validation_rules: Dict) -> Dict:
        """验证LLM返回的内容"""
        validation_result = {
            'valid': True,
            'errors': [],
            'warnings': []
        }
        
        # 检查内容长度
        if 'min_length' in validation_rules and len(response) < validation_rules['min_length']:
            validation_result['valid'] = False
            validation_result['errors'].append(f"内容长度不足，最少需要{validation_rules['min_length']}字符")
        
        if 'max_length' in validation_rules and len(response) > validation_rules['max_length']:
            validation_result['warnings'].append(f"内容过长，建议不超过{validation_rules['max_length']}字符")
        
        # 检查关键词
        if 'required_keywords' in validation_rules:
            for keyword in validation_rules['required_keywords']:
                if keyword.lower() not in response.lower():
                    validation_result['warnings'].append(f"建议包含关键词: {keyword}")
        
        return validation_result
    
    def get_provider_info(self) -> Dict:
        """获取当前LLM提供商信息"""
        return {
            'provider': self.provider,
            'model': self.model,
            'base_url': self.base_url,
            'max_tokens': self.max_tokens,
            'temperature': self.temperature
        }
    
    def test_connection(self) -> Dict:
        """测试LLM连接"""
        try:
            test_prompt = "请回复'连接成功'"
            result = self.generate_text(test_prompt, max_tokens=10)
            return {
                'success': True,
                'message': '连接成功',
                'response': result,
                'provider': self.provider
            }
        except Exception as e:
            return {
                'success': False,
                'error': str(e),
                'provider': self.provider
            }
